#include "JudgeDredd.h"
#include "GomokuBitmask.h"
#include "GameException.h"

JudgeDredd::JudgeDredd(void)
{
}

JudgeDredd::~JudgeDredd(void)
{
}

void	JudgeDredd::putPieceOnMap(GameInfo& game, coord_t& coord)
{
	this->twinTriple(game, coord);
	game.putPieceOnMap(coord);
	game.incScore(takeAPiece(game, coord));
	this->lookAlignement(game, coord, 0, NORTH);
	game.endRoundOfPlayer();
}

void	JudgeDredd::putPieceOnMap2(GameInfo game, coord_t& coord)
{
	this->twinTriple(game, coord);
	game.putPieceOnMap(coord);
	game.incScore(takeAPiece(game, coord));
	this->lookAlignement(game, coord, 0, NORTH);
	game.endRoundOfPlayer();
}


void	JudgeDredd::twinTriple(GameInfo game, coord_t& coord)
{
	int**	tmp;
	int		count;

	game.putPieceOnMap(coord);
	tmp = game.getMap();
	
	if ((count = checkTTripleH(tmp, coord, game.getCurrentPlayer(), 0)) > 1)
	{
		const GameExceptionTwinTriple& exc = GameExceptionTwinTriple();
		throw exc;
	}
	if ((count += checkTTripleV(tmp, coord, game.getCurrentPlayer(), 0)) > 1)
	{
		const GameExceptionTwinTriple& exc = GameExceptionTwinTriple();
		throw exc;
	}
	if ((count += checkTTripleDNS(tmp, coord, game.getCurrentPlayer(), 0)) > 1)
	{
		const GameExceptionTwinTriple& exc = GameExceptionTwinTriple();
		throw exc;
	}
	if ((count += checkTTripleDSN(tmp, coord, game.getCurrentPlayer(), 0)) > 1)
	{
		const GameExceptionTwinTriple& exc = GameExceptionTwinTriple();
		throw exc;
	}
}

int		JudgeDredd::checkTTripleH(int** map, coord_t& coord, int cPlayer, int tell)
{
	int	nb = NBH(map[coord.y][coord.x]);
	int count = 0;

	if ( nb <= 3 && 
		(map[coord.y][coord.x] & TLH) != TLH && 
		(map[coord.y][coord.x] & TRH) != TRH)
	{
		if (nb == 3)
		{
			if ((coord.y - 1) >= 0 && 
				map[coord.y - 1][coord.x] != 0 && tell == 0)
			{
				coord.y -= 1;
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.y += 1;
			}
			if ((coord.y - 2) >= 0 && (coord.y + 1) < LENGTHBOARD &&
				map[coord.y - 2][coord.x] != 0 &&
				map[coord.y + 1][coord.x] == 0  && tell == 0)
			{
				coord.y -= 2;
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.y += 2;
			}
			if ((coord.y + 1) < LENGTHBOARD &&
				map[coord.y + 1][coord.x] != 0  && tell == 0)
			{
				coord.y += 1;
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.y -= 1;
			}
			if ((coord.y - 1) >= 0 && (coord.y + 2) < LENGTHBOARD &&
				map[coord.y + 2][coord.x] != 0 &&
				map[coord.y - 1][coord.x] == 0  && tell == 0)
			{
				coord.y += 2;
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.y -= 2;
			}
			return ++count;
		}
		if (nb == 2)
		{
			if ((coord.y - 3) >= 0 && map[coord.y - 1][coord.x] != 0 &&
				map[coord.y - 3][coord.x] != 0 &&
				isOpposite(cPlayer, map[coord.y - 3][coord.x]) == false &&
				NBH(map[coord.y - 3][coord.x]) == 1 &&
				(map[coord.y - 3][coord.x] & TLH) != TLH)
			{
				if (tell == 0)
				{
					coord.y -= 1;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y -= 2;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y += 3;
				}
				return ++count;
			}
			if ((coord.y - 2) >=0 && map[coord.y - 2][coord.x] != 0 &&
				isOpposite(cPlayer, map[coord.y - 2][coord.x]) == false &&
				NBH(map[coord.y - 2][coord.x]) == 1 &&
				(map[coord.y - 2][coord.x] & TLH) != TLH)
			{
				if (tell == 0)
				{
					coord.y -= 2;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y += 3;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y -= 1;
				}
				return ++count;
			}
			if ((coord.y + 3) < LENGTHBOARD && map[coord.y + 1][coord.x] != 0 &&
				map[coord.y + 3][coord.x] != 0 &&
				isOpposite(cPlayer, map[coord.y + 3][coord.x]) == false &&
				NBH(map[coord.y + 3][coord.x]) == 1 &&
				(map[coord.y + 3][coord.x] & TRH) != TRH)
			{
				if (tell == 0)
				{
					coord.y += 1;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y -= 1;
					coord.y += 3;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y -= 3;
				}
				return ++count;
			}
			if ((coord.y + 2) < LENGTHBOARD && map[coord.y + 2][coord.x] != 0 &&
				isOpposite(cPlayer, map[coord.y + 2][coord.x]) == false &&
				NBH(map[coord.y + 2][coord.x]) == 1 &&
				(map[coord.y + 2][coord.x] & TRH) != TRH)
			{
				if (tell == 0)
				{
					coord.y -= 1;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y += 1;
					coord.y += 2;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y -= 2;
				}
				return ++count;
			}
		}
		if (nb == 1)
		{
			if ((coord.y - 2) >= 0 &&
				map[coord.y - 2][coord.x] != 0 &&
				isOpposite(cPlayer, map[coord.y - 2][coord.x]) == false &&
				(NBH(map[coord.y - 2][coord.x])) == 2 &&
				(map[coord.y - 2][coord.x] & TLH) != TLH)
			{
					if (tell == 0)
				{
					coord.y -= 2;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y--;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y += 3;
				}
				return ++count;
			}
			if ((coord.y + 2) < LENGTHBOARD &&
				map[coord.y + 2][coord.x] != 0 &&
				isOpposite(cPlayer, map[coord.y + 2][coord.x]) == false &&
				NBH(map[coord.y + 2][coord.x]) == 2 &&
				(map[coord.y + 2][coord.x] & TRH) != TRH)
			{
				if (tell == 0)
				{
					coord.y += 2;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y++;
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.y -= 3;
				}
				return ++count;
			}
		}
	}
	return 0;
}

int		JudgeDredd::checkTTripleV(int** map, coord_t& coord, int cPlayer, int tell)
{
	int	nb = NBV(map[coord.y][coord.x]);
	int count = 0;

	if ( nb <= 3 && 
		(map[coord.y][coord.x] & TLV) != TLV && 
		(map[coord.y][coord.x] & TRV) != TRV)
	{
		if (nb == 3)
		{
			if ((coord.x - 1) >= 0 && 
				map[coord.y][coord.x - 1] != 0)
			{
				coord.x -= 1;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.x += 1;
			}
			if ((coord.x - 2) >= 0 && (coord.x + 1) < LENGTHBOARD &&
				map[coord.y][coord.x - 2] != 0 &&
				map[coord.y][coord.x + 1] == 0)
			{
				coord.x -= 2;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.x += 2;
			}
			if ((coord.x + 1) < LENGTHBOARD &&
				map[coord.y + 1][coord.x] != 0)
			{
				coord.x += 1;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.x -= 1;
			}
			if ((coord.x - 1) >= 0 && (coord.x + 2) < LENGTHBOARD &&
				map[coord.y][coord.x + 2] != 0 &&
				map[coord.y][coord.x - 1] == 0)
			{
				coord.x += 2;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.x -= 2;
			}
			return ++count;
		}
		if (nb == 2)
		{
			if ((coord.x - 3) >= 0 && map[coord.y][coord.x - 1] != 0 &&
				map[coord.y][coord.x - 3] != 0 &&
				isOpposite(cPlayer, map[coord.y][coord.x - 3]) == false &&
				NBV(map[coord.y][coord.x - 3]) == 1 &&
				(map[coord.y][coord.x - 3] & TLV) != TLV)
			{
				
				if (tell == 0)
				{
					coord.x -= 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 3;
				}
				return ++count;
			}
			if ((coord.x - 2) >=0 && map[coord.y][coord.x - 2] != 0 &&
				isOpposite(cPlayer, map[coord.y][coord.x - 2]) == false &&
				NBV(map[coord.y][coord.x - 2]) == 1 &&
				(map[coord.y][coord.x - 2] & TLV) != TLV)
			{
				if (tell == 0)
				{
					coord.x += 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 3;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 2;
				}
				return ++count;
			}
			if ((coord.x + 3) < LENGTHBOARD && map[coord.y][coord.x + 1] != 0 &&
				map[coord.y][coord.x + 3] != 0 &&
				isOpposite(cPlayer, map[coord.y][coord.x + 3]) == false &&
				NBV(map[coord.y][coord.x + 3]) == 1 &&
				(map[coord.y][coord.x + 3] & TRV) != TRV)
			{
				if (tell == 0)
				{
					coord.x += 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 3;
				}
				return ++count;
			}
			if ((coord.x + 2) < LENGTHBOARD && map[coord.y][coord.x + 2] != 0 &&
				isOpposite(cPlayer, map[coord.y][coord.x + 2]) == false &&
				NBV(map[coord.y][coord.x + 2]) == 1 &&
				(map[coord.y][coord.x + 2] & TRV) != TRV)
			{
				if (tell == 0)
				{
					coord.x -= 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 3;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 2;
				}
				return ++count;
			}
		}
		if (nb == 1)
		{
			if ((coord.x - 2) >= 0 &&
				map[coord.y][coord.x - 2] != 0 &&
				isOpposite(cPlayer, map[coord.y][coord.x - 2]) == false &&
				NBV(map[coord.y][coord.x - 2]) == 2 &&
				(map[coord.y][coord.x - 2] & TLV) != TLV)
			{
				if (tell == 0)
				{
					coord.x -= 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x--;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 3;
				}
				return ++count;
			}
			if ((coord.x + 2) < LENGTHBOARD &&
				map[coord.y][coord.x + 2] != 0 &&
				isOpposite(cPlayer, map[coord.y][coord.x + 2]) == false &&
				NBV(map[coord.y][coord.x + 2]) == 2 &&
				(map[coord.y][coord.x + 2] & TRV) != TRV)
			{
				if (tell == 0)
				{
					coord.x += 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x++;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 3;
				}
				return ++count;
			}
		}
	}
	return 0;
}

int		JudgeDredd::checkTTripleDNS(int** map, coord_t& coord, int cPlayer, int tell)
{
	int	nb = NBDNS(map[coord.y][coord.x]);
	int count = 0;

	if ( nb <= 3 && 
		(map[coord.y][coord.x] & TLDNS) != TLDNS && 
		(map[coord.y][coord.x] & TRDNS) != TRDNS)
	{
		if (nb == 3)
		{
			if ((coord.x - 1) >= 0 && (coord.y - 1) >= 0 &&
				map[coord.y - 1][coord.x - 1] != 0)
			{
				coord.x -= 1;
				coord.y -= 1;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.x += 1;
				coord.y += 1;
			}
			if ((coord.x - 2) >= 0 && (coord.x + 1) < LENGTHBOARD &&
				(coord.y - 2) >= 0 && (coord.y + 1) < LENGTHBOARD &&
				map[coord.y - 2][coord.x - 2] != 0 &&
				map[coord.y + 1][coord.x + 1] == 0)
			{
				coord.x -= 2;
				coord.y -= 2;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.x += 2;
				coord.y += 2;
			}
			if ((coord.x + 1) < LENGTHBOARD &&
				(coord.y + 1) < LENGTHBOARD &&
				map[coord.y + 1][coord.x + 1] != 0)
			{
				coord.x += 1;
				coord.y += 1;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.x -= 1;
				coord.y -= 1;
			}
			if ((coord.x - 1) >= 0 && (coord.x + 2) < LENGTHBOARD &&
				(coord.y - 1) >= 0 && (coord.y + 2) < LENGTHBOARD &&
				map[coord.y + 2][coord.x + 2] != 0 &&
				map[coord.y - 1][coord.x - 1] == 0)
			{
				coord.x += 2;
				coord.y += 2;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDSN(map, coord, cPlayer, 1);
				coord.x -= 2;
				coord.y -= 2;
			}
			return ++count;
		}
		if (nb == 2)
		{
			if ((coord.x - 3) >= 0 && (coord.y - 3) >= 0 && 
				map[coord.y - 1][coord.x - 1] != 0 &&
				map[coord.y - 3][coord.x - 3] != 0 &&
				isOpposite(cPlayer, map[coord.y - 3][coord.x - 3]) == false &&
				NBDNS(map[coord.y - 3][coord.x - 3]) == 1 &&
				(map[coord.y - 3][coord.x - 3] & TLDNS) != TLDNS)
			{
				if (tell == 0)
				{
					coord.y -= 1;
					coord.x -= 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 2;
					coord.y -= 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 3;
					coord.y += 3;
				}
				return ++count;
			}
			if ((coord.x - 2) >=0 && (coord.y - 2) >= 0 &&
				map[coord.y - 2][coord.x - 2] != 0 &&
				isOpposite(cPlayer, map[coord.y - 2][coord.x - 2]) == false &&
				NBDNS(map[coord.y - 2][coord.x - 2]) == 1 &&
				(map[coord.y - 2][coord.x - 2] & TLDNS) != TLDNS)
			{
				if (tell == 0)
				{
					coord.x += 1;
					coord.y += 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 3;
					coord.y -= 3;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 2;
					coord.y += 2;
				}
				return ++count;
			}
			if ((coord.x + 3) < LENGTHBOARD && (coord.y + 3) < LENGTHBOARD && 
				map[coord.y + 1][coord.x + 1] != 0 &&
				map[coord.y + 3][coord.x + 3] != 0 &&
				isOpposite(cPlayer, map[coord.y + 3][coord.x + 3]) == false &&
				NBDNS(map[coord.y + 3][coord.x + 3]) == 1 &&
				(map[coord.y + 3][coord.x + 3] & TRDNS) != TRDNS)
			{
				if (tell == 0)
				{
					coord.x += 1;
					coord.y += 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 2;
					coord.y += 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 3;
					coord.y -= 3;
				}
				return ++count;
			}
			if ((coord.x + 2) < LENGTHBOARD && (coord.y + 2) < LENGTHBOARD &&
				map[coord.y + 2][coord.x + 2] != 0 &&
				isOpposite(cPlayer, map[coord.y + 2][coord.x + 2]) == false &&
				NBDNS(map[coord.y + 2][coord.x + 2]) == 1 &&
				(map[coord.y + 2][coord.x + 2] & TRDNS) != TRDNS)
			{
				if (tell == 0)
				{
					coord.x -= 1;
					coord.y -= 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 2;
					coord.y += 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 2;
					coord.y -= 2;
				}
				return ++count;
			}
		}
		if (nb == 1)
		{
			if ((coord.x - 2) >= 0 && (coord.y - 2) >= 0 &&
				map[coord.y - 2][coord.x - 2] != 0 &&
				isOpposite(cPlayer, map[coord.y - 2][coord.x - 2]) == false &&
				NBDNS(map[coord.y - 2][coord.x - 2]) == 2 &&
				(map[coord.y - 2][coord.x - 2] & TLDNS) != TLDNS)
			{
				if (tell == 0)
				{
					coord.x -= 2;
					coord.y -= 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x--;
					coord.y--;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x += 3;
					coord.y += 3;
				}
				return ++count;
			}
			if ((coord.x + 2) < LENGTHBOARD && (coord.y + 2) < LENGTHBOARD &&
				map[coord.y + 2][coord.x + 2] != 0 &&
				isOpposite(cPlayer, map[coord.y + 2][coord.x + 2]) == false &&
				NBDNS(map[coord.y + 2][coord.x + 2]) == 2 &&
				(map[coord.y + 2][coord.x + 2] & TRDNS) != TRDNS)
			{
				if (tell == 0)
				{
					coord.x += 2;
					coord.y += 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x++;
					coord.y++;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDSN(map, coord, cPlayer, 1);
					coord.x -= 3;
					coord.y -= 3;
				}
				return ++count;
			}
		}
	}
	return 0;
}

int		JudgeDredd::checkTTripleDSN(int** map, coord_t& coord, int cPlayer, int tell)
{
	int	nb = NBDSN(map[coord.y][coord.x]);
	int count = 0;

	if ( nb <= 3 && 
		(map[coord.y][coord.x] & TLDSN) != TLDSN && 
		(map[coord.y][coord.x] & TRDSN) != TRDSN)
	{
		if (nb == 3)
		{
			if ((coord.x - 1) >= 0 && (coord.y + 1) < LENGTHBOARD &&
				map[coord.y + 1][coord.x - 1] != 0)
			{
				coord.x -= 1;
				coord.y += 1;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				coord.x += 1;
				coord.y -= 1;
			}
			if ((coord.x - 2) >= 0 && (coord.x + 1) < LENGTHBOARD &&
				(coord.y - 1) >= 0 && (coord.y + 2) < LENGTHBOARD &&
				map[coord.y + 2][coord.x - 2] != 0 &&
				map[coord.y - 1][coord.x + 1] == 0)
			{
				coord.x -= 2;
				coord.y += 2;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				coord.x += 2;
				coord.y -= 2;
			}
			if ((coord.x + 1) < LENGTHBOARD &&
				(coord.y - 1) >= 0 &&
				map[coord.y - 1][coord.x + 1] != 0)
			{
				coord.x += 1;
				coord.y -= 1;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				coord.x -= 1;
				coord.y += 1;
			}
			if ((coord.x - 1) >= 0 && (coord.x + 2) < LENGTHBOARD &&
				(coord.y - 2) >= 0 && (coord.y + 1) < LENGTHBOARD &&
				map[coord.y - 2][coord.x + 2] != 0 &&
				map[coord.y + 1][coord.x - 1] == 0)
			{
				coord.x += 2;
				coord.y -= 2;
				count += checkTTripleH(map, coord, cPlayer, 1);
				count += checkTTripleV(map, coord, cPlayer, 1);
				count += checkTTripleDNS(map, coord, cPlayer, 1);
				coord.x -= 2;
				coord.y += 2;
			}
			return ++count;
		}
		if (nb == 2)
		{
			if ((coord.x - 3) >= 0 && (coord.y + 3) < LENGTHBOARD && 
				map[coord.y + 1][coord.x - 1] != 0 &&
				map[coord.y + 3][coord.x - 3] != 0 &&
				isOpposite(cPlayer, map[coord.y + 3][coord.x - 3]) == false &&
				NBDSN(map[coord.y + 3][coord.x - 3]) == 1 &&
				(map[coord.y + 3][coord.x - 3] & TLDSN) != TLDSN)
			{
				if (tell == 0)
				{
					
					coord.x -= 1;
					coord.y += 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x -= 2;
					coord.y += 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x += 3;
					coord.y -= 3;
				}
				return ++count;
			}
			if ((coord.x - 2) >=0 && (coord.y + 2) < LENGTHBOARD &&
				map[coord.y + 2][coord.x - 2] != 0 &&
				isOpposite(cPlayer, map[coord.y + 2][coord.x - 2]) == false &&
				NBDSN(map[coord.y + 2][coord.x - 2]) == 1 &&
				(map[coord.y + 2][coord.x - 2] & TLDSN) != TLDSN)
			{
				if (tell == 0)
				{
					
					coord.x += 1;
					coord.y -= 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x -= 3;
					coord.y += 3;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x += 2;
					coord.y -= 2;
				}
				return ++count;
			}
			if ((coord.x + 3) < LENGTHBOARD && (coord.y - 3) >= 0 && 
				map[coord.y - 1][coord.x + 1] != 0 &&
				map[coord.y - 3][coord.x + 3] != 0 &&
				isOpposite(cPlayer, map[coord.y - 3][coord.x + 3]) == false &&
				NBDSN(map[coord.y - 3][coord.x + 3]) == 1 &&
				(map[coord.y - 3][coord.x + 3] & TRDSN) != TRDSN)
			{
				if (tell == 0)
				{
					coord.x += 1;
					coord.y -= 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x += 2;
					coord.y -= 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x -= 3;
					coord.y += 3;
				}
				return ++count;
			}
			if ((coord.x + 2) < LENGTHBOARD && (coord.y - 2) >= 0 &&
				map[coord.y - 2][coord.x + 2] != 0 &&
				isOpposite(cPlayer, map[coord.y - 2][coord.x + 2]) == false &&
				NBDSN(map[coord.y - 2][coord.x + 2]) == 1 &&
				(map[coord.y - 2][coord.x + 2] & TRDSN) != TRDSN)
			{
				if (tell == 0)
				{
					coord.x -= 1;
					coord.y += 1;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x += 3;
					coord.y -= 3;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x -= 2;
					coord.y += 2;
				}
				return ++count;
			}
		}
		if (nb == 1)
		{
			if ((coord.x - 2) >= 0 && (coord.y + 2) < LENGTHBOARD &&
				map[coord.y + 2][coord.x - 2] != 0 &&
				isOpposite(cPlayer, map[coord.y + 2][coord.x - 2]) == false &&
				NBDSN(map[coord.y + 2][coord.x - 2]) == 2 &&
				(map[coord.y + 2][coord.x - 2] & TLDSN) != TLDSN)
			{
				if (tell == 0)
				{
					coord.x -= 2;
					coord.y += 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x--;
					coord.y++;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x += 3;
					coord.y -= 3;
				}
				return ++count;
			}
			if ((coord.x + 2) < LENGTHBOARD && (coord.y - 2) >= 0 &&
				map[coord.y - 2][coord.x + 2] != 0 &&
				isOpposite(cPlayer, map[coord.y - 2][coord.x + 2]) == false &&
				NBDSN(map[coord.y - 2][coord.x + 2]) == 2 &&
				(map[coord.y - 2][coord.x + 2] & TRDSN) != TRDSN)
			{
				if (tell == 0)
				{
					coord.x += 2;
					coord.y -= 2;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x++;
					coord.y--;
					count += checkTTripleH(map, coord, cPlayer, 1);
					count += checkTTripleV(map, coord, cPlayer, 1);
					count += checkTTripleDNS(map, coord, cPlayer, 1);
					coord.x -= 3;
					coord.y += 3;
				}
				return ++count;
			}
		}
	}
	return 0;
}

char	JudgeDredd::takeAPiece(GameInfo& game, coord_t& coord)
{
	char count = 0;
	if (coord.y > 2 && 
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y - 1][coord.x]) == true &&
		(game.getMap()[coord.y - 1][coord.x] & TOTALH) == TAKENMASKH)
		count++, game.takeOffPieceOnBoard(coord.y - 1, coord.x, NORTH);

	if (coord.y + 3 < LENGTHBOARD && 
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y + 1][coord.x]) == true &&
		(game.getMap()[coord.y + 1][coord.x] & TOTALH) == TAKENMASKH)
		count++, game.takeOffPieceOnBoard(coord.y + 1, coord.x, SOUTH);
	
	if (coord.x > 2 && 
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y][coord.x - 1]) == true &&
		(game.getMap()[coord.y][coord.x - 1] & TOTALV) == TAKENMASKV)
		count++, game.takeOffPieceOnBoard(coord.y, coord.x - 1, WEST);

	if (coord.x + 3 < LENGTHBOARD && 
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y][coord.x + 1]) == true &&
		(game.getMap()[coord.y][coord.x + 1] & TOTALV) == TAKENMASKV)
		count++, game.takeOffPieceOnBoard(coord.y, coord.x + 1, EAST);

	if (coord.x >= 2 && coord.y >= 2 &&
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y - 1 ][coord.x - 1]) == true &&
		(game.getMap()[coord.y - 1][coord.x - 1] & TOTALDNS) == TAKENMASKDNS)
		count++, game.takeOffPieceOnBoard(coord.y - 1, coord.x - 1, NORTHWEST);

	if (coord.x + 3 < LENGTHBOARD && coord.y + 3 < LENGTHBOARD &&
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y + 1 ][coord.x + 1]) == true &&
		(game.getMap()[coord.y + 1][coord.x + 1] & TOTALDNS) == TAKENMASKDNS)
		count++, game.takeOffPieceOnBoard(coord.y + 1, coord.x + 1, SOUTHEAST);

	if (coord.x >= 2 && coord.y + 3 < LENGTHBOARD &&
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y + 1 ][coord.x - 1]) == true &&
		(game.getMap()[coord.y + 1][coord.x - 1] & TOTALDSN) == TAKENMASKDSN)
		count++, game.takeOffPieceOnBoard(coord.y + 1, coord.x - 1, SOUTHWEST);
	int c;
	if (coord.x + 3 < LENGTHBOARD && coord.y >= 2 &&
		isOpposite(game.getCurrentPlayer(), game.getMap()[coord.y - 1 ][coord.x + 1]) == true &&
		(c = (game.getMap()[coord.y - 1][coord.x + 1] & TOTALDSN)) == TAKENMASKDSN)
		count++, game.takeOffPieceOnBoard(coord.y - 1, coord.x + 1, NORTHEAST);
	return count;
}

void	JudgeDredd::lookAlignement(GameInfo& game, coord_t& coord, int p, Way way)

{
	int		count;
	int		stop = 0;
	int**	tmp = game.getMap();
	int		n[4];

	

	n[0] = 0;
	n[1] = 0;
	n[2] = 0;
	n[3] = 0;
	
	if (p <= 1)
	{
		if ((p == 1 && way == NORTH))
			stop |= (1 | 2);
		if ((p == 1 && way == WEST))
			stop |= (4 | 8);
		if ((p == 1 && way == NORTHWEST))
			stop |= (16 | 32);
		if ((p == 1 && way == SOUTHWEST))
			stop |= (64 | 128);
	}
	else
		stop = 255;
	p++;
	for (count = 0; count < LENGTHBOARD && stop < 255; count++)
	{
		if (!(stop & 1))
		{
			if ((coord.y - count) >= 0 &&
				tmp[coord.y - count][coord.x] != 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y - count][coord.x]) != true)
			{
				stop |= checkTaken(tmp[coord.y - count][coord.x], NORTH);
				if (count > 0)
				{
					coord.y -= count;
					lookAlignement(game, coord, p, NORTH);
					coord.y += count;
				}
			}
			else
				stop |= 1;
			if (!(stop & 1))
				n[0]++;
		}

		if (!(stop & 2) && count > 0)
		{
			if ((coord.y + count) < LENGTHBOARD &&
				tmp[coord.y + count][coord.x] != 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y + count][coord.x]) != true)
			{
				stop |= checkTaken(tmp[coord.y + count][coord.x], SOUTH);
				coord.y += count;
				lookAlignement(game, coord, p, NORTH);
				coord.y -= count;
			}
			else
				stop |= 2;
			if (!(stop & 2))
				n[0]++;
		}

		if (!(stop & 4))
		{
			if ((coord.x - count) >= 0 &&
				tmp[coord.y][coord.x - count] != 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y][coord.x - count]) != true)
			{
				stop |= checkTaken(tmp[coord.y][coord.x - count], WEST);
				if (count > 0)
				{
					coord.x -= count;
					lookAlignement(game, coord, p, WEST);
					coord.x += count;
				}
			}
			else
				stop |= 4;
			if (!(stop & 4))
				n[1]++;
		}

		if (!(stop & 8) && count > 0)
		{
			if ((coord.x + count) < LENGTHBOARD &&
				tmp[coord.y][coord.x + count] != 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y][coord.x + count]) != true)
			{
				stop |= checkTaken(tmp[coord.y][coord.x + count], EAST);
				coord.x += count;
				lookAlignement(game, coord, p, WEST);
				coord.x -= count;
			}
			else
				stop |= 8;
			if (!(stop & 8))
				n[1]++;
		}

		if (!(stop & 16))
		{
			if ((coord.x - count) >= 0 && (coord.y - count) >= 0 &&
				tmp[coord.y - count][coord.x - count] != 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y - count][coord.x - count]) != true)
			{
				stop |= checkTaken(tmp[coord.y - count][coord.x - count], NORTHWEST);
				if (count > 0)
				{
					coord.x -= count;
					coord.y -= count;
					lookAlignement(game, coord, p, NORTHWEST);
					coord.x += count;
					coord.y += count;
				}
			}
			else
				stop |= 16;
			if (!(stop & 16))
				n[2]++;
		}

		if (!(stop & 32) && count > 0)
		{
			if ((coord.x + count) < LENGTHBOARD && (coord.y + count) < LENGTHBOARD &&
				tmp[coord.y + count][coord.x + count] != 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y + count][coord.x + count]) != true)
			{
				stop |= checkTaken(tmp[coord.y + count][coord.x + count], SOUTHEAST);
				coord.x += count;
				coord.y += count;
				lookAlignement(game, coord, p, NORTHWEST);
				coord.x -= count;
				coord.y -= count;
			}
			else
				stop |= 32;
			if (!(stop & 32))
				n[2]++;
		}

		if (!(stop & 64))
		{
			if ((coord.x + count) < LENGTHBOARD && (coord.y - count) >= 0 &&
				tmp[coord.y - count][coord.x + count] != 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y - count][coord.x + count]) != true)
			{
				stop |= checkTaken(tmp[coord.y - count][coord.x + count], NORTHEAST);
				if (count > 0)
				{
					coord.x += count;
					coord.y -= count;
					lookAlignement(game, coord, p, SOUTHWEST);
					coord.x -= count;
					coord.y += count;
				}
			}
			else
				stop |= 64;
			if (!(stop & 64))
				n[3]++;
		}

		if (!(stop & 128) && count > 0)
		{
			if ((coord.x - count) >= 0 && (coord.y + count) < LENGTHBOARD &&
				tmp[coord.y + count][coord.x - count] != 0 &&
				isOpposite(game.getCurrentPlayer(), tmp[coord.y + count][coord.x - count]) != true)
			{
				stop |= checkTaken(tmp[coord.y + count][coord.x - count], SOUTHWEST);
				coord.x -= count;
				coord.y += count;
				lookAlignement(game, coord, p, SOUTHWEST);
				coord.x += count;
				coord.y -= count;
			}
			else
				stop |= 128;
			if (!(stop & 128))
				n[3]++;
		}

		if (n[0] >= 5 || n[1] >= 5 || n[2] >= 5 || n[3] >= 5)
		{
            GameExceptionWinByAlignement& exc = GameExceptionWinByAlignement();
			throw exc;
                        
		}
	}
}

int		JudgeDredd::checkTaken(int point, Way dir)
{
	int ret = 0;
	int tmp = (point & TOTALH);

	if (tmp == (DPH | TLH) || 
		tmp == (DPH | TRH))
		return makeAnswer(dir);
	tmp = (point & TOTALV);
	if (tmp == (DPV | TLV) || 
		tmp == (DPV | TRV))
		return makeAnswer(dir);
	tmp = (point & TOTALDNS);
	if (tmp == (DPDNS | TLDNS) || 
		tmp == (DPDNS | TRDNS))
		return makeAnswer(dir);
	tmp = (point & TOTALDSN);
	if (tmp == (DPDSN | TLDSN) || 
		tmp == (DPDSN | TRDSN))
		return makeAnswer(dir);
	return 0;
}

int		JudgeDredd::makeAnswer(Way dir)
{
	if (dir == NORTH)
		return 1;
	if (dir == SOUTH)
		return 2;
	if (dir == WEST)
		return 4;
	if (dir == EAST)
		return 8;
	if (dir == NORTHWEST)
		return 16;
	if (dir == SOUTHEAST)
		return 32;
	if (dir == NORTHEAST)
		return 64;
	if (dir == SOUTHWEST)
		return 128;
	return 0;
}
